import { config, srcDir, distDir, saveconfig } from './config.js'
import fsExtra from 'fs-extra/esm'
import path from 'path'
import { execAsync, getSubDirs } from './util.js'

import { glob } from 'glob'
import axios from 'axios'
import mime from 'mime-types'
import fs from 'fs/promises'

// import { chromium } from 'playwright'
import { chromium } from 'playwright-extra'
import stealth from 'puppeteer-extra-plugin-stealth'
chromium.use(stealth())

import { PdfDocument } from '@ironsoftware/ironpdf'

async function main() {
  await Promise.all([task('electron'), task('playwright'), task('download'), task('iron')])
}

async function task(type = 'electron') {
  const urls = fsExtra.readJSONSync('./urls.json').urls

  for (let i = config[type]; i < urls.length; i++) {
    const url = urls[i]

    try {
      if (type == 'electron') {
        await electronPdf(url, path.join(srcDir, `electron/${i}.pdf`))
      } else if (type == 'playwright') {
        await playwrightPdf(url, path.join(srcDir, `playwright/${i}.pdf`))
      } else if (type == 'download') {
        await downloadPdf(url, path.join(srcDir, `download/${i}.pdf`))
      } else if (type == 'iron') {
        await ironPdf(url, path.join(srcDir, `iron/${i}.pdf`))
      }
    } catch (e) {
      console.error(e)
    }

    saveconfig()
    config[type] = i + 1
  }

  await moveLargestPdfToDist(srcDir, distDir)
}

async function moveLargestPdfToDist(srcDir, distDir) {
  const subDirs = getSubDirs(srcDir)

  for (let subDir of subDirs) {
    const dirPath = path.join(srcDir, subDir)
    const pdfFiles = await glob(`${dirPath}/*.*`)

    let largestPdf = null
    let largestPdfSize = 0

    // 找到最大文件
    for (let file of pdfFiles) {
      const filePath = path.join(dirPath, file)
      const stats = fsExtra.statSync(filePath)

      if (stats.size > largestPdfSize) {
        largestPdfSize = stats.size
        largestPdf = filePath
      }
    }

    // 如果找到了最大的 PDF 文件，且文件大小大于 100KB
    if (largestPdf && largestPdfSize > 100 * 1024) {
      const fileName = path.basename(largestPdf)
      const newFileName = `${subDir}-${fileName}`
      const distPath = path.join(distDir, newFileName)

      // 移动文件到 dist 目录
      fsExtra.moveSync(largestPdf, distPath)
      console.log(`Moved largest PDF file ${fileName} from ${subDir} to dist directory as ${newFileName}.`)
    }
  }
}

// https://github.com/fraserxu/docker-tape-run D:\Git\1.pdf
async function electronPdf(url, outputPath) {
  console.log('[electronPdf] 开始')

  try {
    // 转义 URL 和路径中的特殊字符，增强命令行安全性
    const escapedUrl = `"${url.replace(/"/g, '\\"')}"`
    const escapedOutputPath = `"${outputPath.replace(/"/g, '\\"')}"`

    // 构建 electron-pdf 命令
    const command = `electron-pdf ${escapedUrl} ${escapedOutputPath} --disable-gpu --printBackground`

    console.log(`执行命令: ${command}`)

    const { stdout, stderr } = await execAsync(command)

    if (stderr) {
      console.warn('命令警告信息:', stderr)
    }

    return stdout
  } catch (error) {
    // 增强错误处理
    if (error.code === 'ENOENT') {
      throw new Error('未找到 electron-pdf 命令，请先运行: npm install electron-pdf -g')
    }
    throw error
  }
}

/**
 * 使用 playwright 生成 PDF
 * @param {string} url - 需要生成 PDF 的 URL
 * @param {string} outputPath - 生成 PDF 的输出路径
 * @returns {Promise<string>} 生成 PDF 的 Promise
 */
async function playwrightPdf(url, outputPath) {
  console.log('[playwrightPdf] 开始')
  try {
    fsExtra.ensureDirSync(path.dirname(outputPath))

    const browser = await chromium.launch({ headless: true, args: ['--allow-file-access-from-files'] })
    const page = await browser.newPage()

    // await page.goto(url, { waitUntil: 'networkidle' })
    // await page.waitForTimeout(3000) // 给SPA页面渲染时间

    await page.goto(url, { waitUntil: 'networkidle', timeout: 60000 })
    await page.waitForSelector('body', { timeout: 30000 })
    await page.waitForTimeout(8000) // 额外等待 8 秒渲染

    await page.pdf({
      path: outputPath,
      format: 'A4',
      printBackground: true,
      landscape: false,
    })

    console.log(`✅ PDF 已成功生成: ${outputPath}`)
    await browser.close()
  } catch (error) {
    console.error('❌ 生成 PDF 失败:', error)
    throw error
  }
}

async function isPdfUrl(url) {
  try {
    // 先检查扩展名
    const ext = path.extname(url).toLowerCase()
    if (ext === '.pdf') return true

    // 发送 HEAD 请求判断内容类型
    const res = await axios.head(url, { timeout: 5000, maxRedirects: 5 })
    const type = res.headers['content-type'] || ''
    return type.includes('application/pdf')
  } catch (err) {
    console.warn('HEAD 请求失败，尝试 GET 检测内容:', url)
    try {
      const res = await axios.get(url, {
        responseType: 'arraybuffer',
        timeout: 5000,
      })
      const type = res.headers['content-type'] || ''
      return type.includes('application/pdf')
    } catch {
      return false
    }
  }
}

/**
 * 直接下载 PDF 文件
 */
async function downloadPdf(url, outputPath) {
  console.log('[downloadPdf] 开始')

  const isPdf = await isPdfUrl(url)
  if (!isPdf) return console.log(`❌ 不是 PDF 文件:${url}`)

  fsExtra.ensureDirSync(path.dirname(outputPath))
  const res = await axios.get(url, { responseType: 'arraybuffer' })
  const type = res.headers['content-type']
  const ext = mime.extension(type) || 'pdf'
  const finalPath = outputPath.endsWith(`.${ext}`) ? outputPath : `${outputPath}.${ext}`

  await fs.writeFile(finalPath, res.data)
  console.log(`✅ PDF 已直接下载: ${finalPath}`)
}

/**
 * 使用 IronPDF 从URL生成并保存PDF
 * @param {string} url - 要转换为PDF的网页URL
 * @param {string} outputPath - PDF文件的输出路径
 */
async function ironPdf(url, outputPath) {
  console.log('[ironPdf] 开始')

  const isPdf = await isPdfUrl(url)
  if (isPdf) return

  try {
    const pdf = await PdfDocument.fromUrl(url)
    await pdf.saveAs(outputPath)

    console.log(`[ironPdf] PDF 已成功保存至: ${outputPath}`)
  } catch (error) {
    console.error('[ironPdf] 错误:', error)
    throw new Error(`使用 IronPDF 生成 PDF 失败: ${error.message}`)
  }
}

main()
